﻿using System.Data;
using System.Data.Entity;
using System.Data.Entity.Validation;
using Timetable.Base.Entities;
using Timetable.Data.Context.Interfaces;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Collections.Generic;
using Timetable.Base.Interfaces.DataSources;
using System.Linq;
using System.Data.Common;

namespace Timetable.Data.Context
{
    public class DataContext: DbContext, IDataContext, IDatabase
    {

        public IDbSet<Department> Departments { get; set; }

        public IDbSet<Auditorium> Auditoriums { get; set; }

        public IDbSet<Faculty> Faculties { get; set; }

        public IDbSet<Building> Buildings { get; set; }

        public IDbSet<Course> Courses { get; set; }

        public IDbSet<Group> Groups { get; set; }

        public IDbSet<Lecturer> Lecturers { get; set; }

        public IDbSet<Schedule> Schedule { get; set; }

        public IDbSet<TutorialType> TutorialTypes { get; set; }

        public IDbSet<Rank> Ranks { get; set; }

        public IDbSet<Time> Times { get; set; }

        public IDbSet<Speciality> Specialities { get; set; }

        public IDbSet<Tutorial> Tutorials { get; set; }

        public IDbSet<ScheduleInfo> ScheduleInfos { get; set; }

        public IDbSet<WeekType> WeekTypes { get; set; }

        public DataContext()
        {
            Initialize();
        }
        
        protected void Initialize()
        {
            Departments = Set<Department>();
            Auditoriums = Set<Auditorium>();
            Faculties = Set<Faculty>();
            Buildings = Set<Building>();
            Courses = Set<Course>();
            Groups = Set<Group>();
            Lecturers = Set<Lecturer>();
            Schedule = Set<Schedule>();
            TutorialTypes = Set<TutorialType>();
            Ranks = Set<Rank>();
            Times = Set<Time>();
            Specialities = Set<Speciality>();
            Tutorials = Set<Tutorial>();
            ScheduleInfos = Set<ScheduleInfo>();
            WeekTypes = Set<WeekType>();

            Configuration.ProxyCreationEnabled = false;
            Configuration.LazyLoadingEnabled = false;
            Configuration.AutoDetectChangesEnabled = false;
        }

        public new void SaveChanges()
        {
            base.SaveChanges();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

            modelBuilder.Entity<ScheduleInfo>().
                HasMany(c => c.Groups).
                WithMany(p => p.ScheduleInfoes).
                Map(m =>
                    {
                        m.MapLeftKey("ScheduleInfo_Id");
                        m.MapRightKey("Group_Id");
                        m.ToTable("ScheduleInfosToGroups");
                    });

            modelBuilder.Entity<ScheduleInfo>().
                HasMany(c => c.Faculties).
                WithMany(p => p.ScheduleInfoes).
                Map(m =>
                {
                    m.MapLeftKey("ScheduleInfo_Id");
                    m.MapRightKey("Faculty_Id");
                    m.ToTable("ScheduleInfosToFaculties");
                });

            modelBuilder.Entity<ScheduleInfo>().
                HasMany(c => c.Specialities).
                WithMany(p => p.ScheduleInfoes).
                Map(m =>
                {
                    m.MapLeftKey("ScheduleInfo_Id");
                    m.MapRightKey("Speciality_Id");
                    m.ToTable("ScheduleInfosToSpecialities");
                });

            modelBuilder.Entity<ScheduleInfo>().
                HasMany(c => c.Courses).
                WithMany(p => p.ScheduleInfoes).
                Map(m =>
                {
                    m.MapLeftKey("ScheduleInfo_Id");
                    m.MapRightKey("Course_Id");
                    m.ToTable("ScheduleInfosToCourses");
                });

            modelBuilder.Entity<ScheduleInfo>().
                HasMany(c => c.LikeAuditoriums).
                WithMany(p => p.ScheduleInfoes).
                Map(m =>
                {
                    m.MapLeftKey("ScheduleInfo_Id");
                    m.MapRightKey("Auditorium_Id");
                    m.ToTable("SheduleInfosToAuditoriums");
                });
        }

        #region IDatabase implementation

        IQueryable<Department> IDatabase.Departments
        {
            get { return Departments; }
        }

        IQueryable<Auditorium> IDatabase.Auditoriums
        {
            get { return Auditoriums; }
        }

        IQueryable<Faculty> IDatabase.Faculties
        {
            get { return Faculties; }
        }

        IQueryable<Speciality> IDatabase.Specialities
        {
            get { return Specialities; }
        }

        IQueryable<Time> IDatabase.Times
        {
            get { return Times; }
        }

        IQueryable<Rank> IDatabase.Ranks
        {
            get { return Ranks; }
        }

        IQueryable<TutorialType> IDatabase.TutorialTypes
        {
            get { return TutorialTypes; }
        }

        IQueryable<Schedule> IDatabase.Schedule
        {
            get { return Schedule; }
        }

        IQueryable<Lecturer> IDatabase.Lecturers
        {
            get { return Lecturers; }
        }

        IQueryable<Group> IDatabase.Groups
        {
            get { return Groups; }
        }

        IQueryable<Course> IDatabase.Courses
        {
            get { return Courses; }
        }

        IQueryable<Building> IDatabase.Buildings
        {
            get { return Buildings; }
        }

        IQueryable<Tutorial> IDatabase.Tutorials
        {
            get { return Tutorials; }
        }

        IQueryable<ScheduleInfo> IDatabase.ScheduleInfos
        {
            get { return ScheduleInfos; }
        }
        IQueryable<WeekType> IDatabase.WeekTypes
        {
            get { return WeekTypes; }
        }

        #endregion
    }
}
